﻿// ----------------------------------------------------------------------------
//  Copyright (C) 成都联宇创新科技有限公司 版权所有。 
//      
//  文件名：DataEncryptionStandard.cs
//  文件功能描述：
//  创建标识：骆智慧 2016/03/02 23:28
//     
//  修改标识：骆智慧  2016/03/10/06:40
//  修改描述：
//  ----------------------------------------------------------------------------

#region 导入名称空间

using System;
using System.IO;
using SysCrypto = System.Security.Cryptography;

#endregion

namespace LightWork.Cryptography
{
    /// <summary>
    /// 数据加密标准（DES）
    /// </summary>
    public class DataEncryptionStandard : CryptoBase
    {
        #region --------------加密-------------

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="password">密码</param>
        /// <param name="salt">salt</param>
        /// <param name="iterations">操作的迭代数</param>
        /// <remarks>salt 大小必须等于或大于 8 字节，并且迭代次数必须大于零。 建议的最小迭代次数为 1000</remarks>
        /// <returns></returns>
        public override byte[] Encrypt(byte[] plaintext, byte[] password, byte[] salt, int iterations)
        {
            using (var memoryStream = new MemoryStream())
            {
                var deriveBytes = new SysCrypto.Rfc2898DeriveBytes(password, salt, iterations);
                var desProvider = new SysCrypto.DESCryptoServiceProvider
                {
                    Key = deriveBytes.GetBytes(8),
                    IV = deriveBytes.GetBytes(8),
                    Mode = SysCrypto.CipherMode.CBC
                };


                using (var cryptoStream = new SysCrypto.CryptoStream(memoryStream
                    , desProvider.CreateEncryptor()
                    , SysCrypto.CryptoStreamMode.Write))
                {
                    cryptoStream.Write(plaintext, 0, plaintext.Length);
                    cryptoStream.FlushFinalBlock();
                }

                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="plaintext">明文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public override string Encrypt(byte[] plaintext, byte[] password)
        {
            var encryptedBytes = Encrypt(plaintext, password, DefaultSalt, 1000);
            return BitConverter.ToString(encryptedBytes).Replace("-", "");
        }

        #endregion

        #region --------------解密-------------

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <param name="password">密码</param>
        /// <param name="salt">salt</param>
        /// <param name="iterations">操作的迭代数</param>
        /// <remarks>salt 大小必须等于或大于 8 字节，并且迭代次数必须大于零。 建议的最小迭代次数为 1000</remarks>
        public override byte[] Decrypt(byte[] ciphertext, byte[] password, byte[] salt, int iterations)
        {
            using (var memoryStream = new MemoryStream())
            {
                var deriveBytes = new SysCrypto.Rfc2898DeriveBytes(password, salt, iterations);
                var desProvider = new SysCrypto.DESCryptoServiceProvider
                {
                    Key = deriveBytes.GetBytes(8),
                    IV = deriveBytes.GetBytes(8),
                    Mode = SysCrypto.CipherMode.CBC
                };

                using (
                    var cryptoStream = new SysCrypto.CryptoStream(memoryStream, desProvider.CreateDecryptor(),
                        SysCrypto.CryptoStreamMode.Write))
                {
                    cryptoStream.Write(ciphertext, 0, ciphertext.Length);
                    cryptoStream.Flush();
                }

                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="ciphertext">密文</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public override string Decrypt(byte[] ciphertext, byte[] password)
        {
            var decryptBytes = Decrypt(ciphertext, password, DefaultSalt, 1000);
            return FromBytes(decryptBytes);
        }

        #endregion
    }
}